<template>
  <!-- 操作弹窗 -->
  <a-modal
    class="crud"
    :mask-closable="props.config?.maskClosable !== false"
    :cancel-text="props.config?.cancelText || '取消'"
    :ok-text="props.config?.okText || '确定'"
    :visible="props.crudModalVisible"
    :title="props.config?.title || '操作'"
    :width="props.config?.width || 800"
    @ok="handleOk"
    @cancel="handleCancel"
  >
    <a-form :model="formValue" :layout="props.config?.layout">
      <a-row>
        <!-- 遍历 crudAddConfig 数组 -->
        <template v-for="item in props.crudAddConfig" :key="item.key">
          <a-col :span="item.span || 12" style="padding: 0 10px">
            <a-form-item
              :label="item.label"
              :colon="props.config?.colon !== false"
              :labelAlign="props.config?.labelAlignh ? props.config?.labelAlignh : 'right'"
              :labelCol="props.config?.labelCol ? { ...props.config.labelCol, width: '120px' } : { width: '120px' }"
            >
              <!-- 根据表单项的类型渲染不同的组件 -->
              <template v-if="isSwitchCheckboxOrRadio(item.type)">
                <component :disabled="item.disabled || false" :is="item.type" :name="item.key" v-model:checked="formValue[item.key]"></component>
              </template>
              <template v-else>
                <component :is="item.type" :name="item.key" v-model:value="formValue[item.key]" :disabled="item.disabled || false">
                  <!-- 遍历 item.options 数组 -->
                  <component v-for="(option, i) in item.options" :key="i" :is="subComponents(item.type)" :value="option.value">{{ option.label }}</component>
                </component>
              </template>
            </a-form-item>
          </a-col>
        </template>
      </a-row>
    </a-form>
  </a-modal>
</template>

<script lang="ts" setup name="crud">
import { TableCrudItemComponentType, TableRecordType } from './types'

const props = defineProps({
  crudModalVisible: {
    type: Boolean,
    required: true
  },
  config: {
    type: Object,
    required: false
  },
  crudAddConfig: {
    type: Object,
    required: false
  },
  crudEditConfig: {
    type: Object,
    required: false
  },
  formData: {
    type: Object,
    required: false
  }
})

/**
 * 定义了一个 form 对象，用于保存当前表单的值。它的初始值是一个空的对象，
 * 然后通过 reduce 方法遍历 crudAddConfig 数组，将每个表单项的 key 属性作为 form 对象的属性名
 * 并将属性值设置为 '' 或 []，具体根据表单项的类型来决定
 */
const form: TableRecordType = props.crudAddConfig?.reduce((acc: TableRecordType, curr: TableRecordType) => {
  const value = curr.type === 'a-checkbox-group' ? [] : ''
  return { ...acc, [curr.key]: value }
}, {})

// 初始化 formValue
const formValue = reactive({ ...form })

// 监听 crudModalVisible 的变化，如果有 formData，则将其赋值给 formValue
watch(
  () => props.crudModalVisible,
  (newVal, oldVal) => {
    if (newVal && props.formData) {
      for (const key in props.formData) {
        // 如果 formValue 中有该属性，则将其值赋为 formData 中对应的值
        if (Object.prototype.hasOwnProperty.call(formValue, key)) {
          formValue[key] = props.formData[key]
        }
      }
    }
  },
  { immediate: true }
)

// 定义了一个 Map，用于存储组件类型和对应的子组件类型
const componentMap = new Map<TableCrudItemComponentType, any>()
componentMap.set('a-input', null) // a-input 组件没有子组件
componentMap.set('a-select', 'a-select-option') // a-select 组件的子组件是 a-select-option
componentMap.set('a-tree-select', null) // a-tree-select 组件没有子组件
componentMap.set('a-radio-group', 'a-radio') // a-radio-group 组件的子组件是 a-radio
componentMap.set('a-checkbox-group', 'a-checkbox') // a-checkbox-group 组件的子组件是 a-checkbox
componentMap.set('a-textarea', null) // a-textarea 组件没有子组件

/**
 * 定义了一个 computed 函数 subComponents，用于根据组件类型获取对应的子组件类型
 * componentMap 是一个 Map，存储了组件类型和对应的子组件类型
 * 如果组件类型不存在于 componentMap 中，则返回 null
 */
const subComponents = computed(() => {
  // 根据组件类型获取对应的子组件类型
  return (type: TableCrudItemComponentType) => {
    const typeValue = componentMap.get(type)
    return typeValue
  }
})

const emits = defineEmits(['handleOk', 'handleCancel'])

const handleOk = () => {
  emits('handleOk', false, formValue)
}
const handleCancel = () => {
  emits('handleCancel', false)
}

// 判断组件类型是否为开关、复选框或单选框
const isSwitchCheckboxOrRadio = (type: string) => {
  return ['a-switch', 'a-checkbox', 'a-radio'].includes(type)
}
</script>

<style lang="less">
@import './index.less';
</style>
